home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
quicspool
/
libglob
/
glob.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
4KB
|
224 lines
static char *rcs= "$Header: glob.c,v 1.1 88/01/15 12:15:45 simpson Rel $";
/*
$Log: glob.c,v $
* Revision 1.1 88/01/15 12:15:45 simpson
* initial release
*
* Revision 0.1 87/12/11 17:18:05 simpson
* beta test
*
*/
#include "glob.h"
#define SLOP 5
#define MAX_SET 0177
/* control codes for regular expression evaluation */
#define PATTERN_ANY '?'
#define PATTERN_CHARACTER 'X'
#define PATTERN_END '$'
#define PATTERN_SET '['
#define PATTERN_SET_MEMBER 'M'
#define PATTERN_SET_RANGE '-'
#define PATTERN_STAR '*'
/*
* Examples (=> denotes `compiles into')
*
* a => Xa
* ? => ?
* [x0-9] => [^EMx-09 (^E is control-E)
* * => *
* END => $
*
* a?[x0-9]* => Xa?[^EMx-09*$
*/
glob_compile (pattern, buffer)
char *pattern;
char *buffer; /* compiled pattern */
{
char *x; /* pointer into compiled pattern */
int c;
int result;
if (pattern == 0 || pattern[0] == 0)
return(GLOB_PATTERN_EMPTY);
x = buffer;
while (x < &buffer[GLOB_MAX_PATTERN - SLOP]) {
c = *pattern++;
if (c == 0) {
*x++ = PATTERN_END;
return(GLOB_OK);
}
switch (c) {
case '?':
*x++ = PATTERN_ANY;
continue;
case '[':
if ((result = compile_set(pattern, x, &buffer[GLOB_MAX_PATTERN - SLOP])) < 0)
return(result);
pattern += result + 1;
x += x[1] + 2;
continue;
case '*':
*x++ = PATTERN_STAR;
continue;
default:
*x++ = PATTERN_CHARACTER;
*x++ = c;
continue;
}
}
return(GLOB_PATTERN_TOO_BIG);
}
int glob_execute (pattern, s)
char *pattern; /* compiled pattern */
char *s; /* string to be matched against */
{
char *current;
int result;
for (;;)
switch (*pattern++) {
case PATTERN_ANY:
if (*s++)
continue;
return(0);
case PATTERN_CHARACTER:
if (*pattern++ == *s++)
continue;
return(0);
case PATTERN_END:
return(*s == 0);
case PATTERN_SET:
if ((result = in_set(pattern, *s++)) == 1) {
pattern += *pattern + 1;
continue;
}
return(result);
case PATTERN_STAR:
current = s;
while (*s++)
continue;
do {
s--;
if (result = glob_execute(pattern, s))
return(result);
} while (s > current);
return(0);
default:
return(GLOB_EXECUTION_ERROR);
}
}
int glob_match (pattern, s)
char *pattern;
char *s;
{
int result;
char buffer[GLOB_MAX_PATTERN];
if ((result = glob_compile(pattern, buffer)) < 0)
return(result);
else
return(glob_execute(buffer, s));
}
/* returns 1 if character c is member of set and 0 otherwise */
static int in_set (set, c)
char *set; /* compiled set pattern */
char c;
{
int n;
if (c == 0)
return(0);
n = *set++;
while (n > 0)
switch (*set++) {
case PATTERN_SET_MEMBER:
if (*set++ == c)
return(1);
n -= 2;
continue;
case PATTERN_SET_RANGE:
if (*set++ <= c && c <= *set++)
return(1);
n -= 3;
continue;
default:
return(GLOB_EXECUTION_ERROR);
}
return(0);
}
#define IS_RANGE(s) (s[1] && s[2] && s[1] == '-' && s[2] != ']')
/* compiles a set returning the number of pattern characters consumed */
static int compile_set (pattern, x, limit)
char *pattern;
char *x;
char *limit;
{
char *slot; /* size of set goes here */
int size; /* number of bytes in compiled set */
char *start = pattern;
if (*pattern == 0)
return(GLOB_BRACKET_MISSING);
*x++ = PATTERN_SET;
slot = x++;
size = 0;
if (IS_RANGE(pattern)) {
if (pattern[0] > pattern[2]) /* pattern[1] == '-' */
return(GLOB_RANGE_INVERTED);
*x++ = PATTERN_SET_RANGE;
*x++ = pattern[0];
*x++ = pattern[2];
pattern += 3;
size += 3;
} else {
*x++ = PATTERN_SET_MEMBER;
*x++ = *pattern++;
size += 2;
}
while (*pattern != ']' && x < limit) {
if (*pattern == 0)
return(GLOB_BRACKET_MISSING);
if (IS_RANGE(pattern)) {
if (pattern[0] > pattern[2]) /* pattern[1] == '-' */
return(GLOB_RANGE_INVERTED);
*x++ = PATTERN_SET_RANGE;
*x++ = pattern[0];
*x++ = pattern[2];
pattern += 3;
size += 3;
} else {
*x++ = PATTERN_SET_MEMBER;
*x++ = *pattern++;
size += 2;
}
}
if (size > MAX_SET)
return(GLOB_SET_TOO_BIG);
*slot = size;
return(pattern - start);
}